package com.local.videoplayer.player;

import android.content.Context;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import com.local.videoplayer.utils.LogUtil;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import tv.danmaku.ijk.media.player.AndroidMediaPlayer;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.TextureMediaPlayer;
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;

/**
 * <p>统一管理MediaPlayer的地方,只有一个mediaPlayer实例，那么不会有多个视频同时播放，也节省资源。</p>
 * <p>Unified management MediaPlayer place, there is only one MediaPlayer instance, then there will
 * be no more video broadcast at the same time, also save resources.</p>
 * Created by Nathen
 * On 2015/11/30 15:39
 */
public class MediaManager
        implements TextureView.SurfaceTextureListener, IMediaPlayer.OnPreparedListener,
                   IMediaPlayer.OnCompletionListener, IMediaPlayer.OnBufferingUpdateListener,
                   IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnErrorListener,
                   IMediaPlayer.OnInfoListener, IMediaPlayer.OnVideoSizeChangedListener{

    public static String TAG = "JieCaoVideoPlayer";

    private static MediaManager JCMediaManager;

    public static TextureView textureView;
    public static SurfaceTexture savedSurfaceTexture;
    public static String CURRENT_PLAYING_URL;
    public static boolean CURRENT_PLING_LOOP;
    public static Map<String, String> MAP_HEADER_DATA;
    public int currentVideoWidth = 0;
    public int currentVideoHeight = 0;

    public static final int HANDLER_PREPARE = 0;
    public static final int HANDLER_RELEASE = 2;
    HandlerThread mMediaHandlerThread;
    MediaHandler mMediaHandler;
    Handler mainThreadHandler;
    /**
     * 使用Android播放器
     */
    private boolean usingAndroidPlayer = false;
    /**
     * 使用编解码器硬编码还是软编码，true 硬编码 false 为软编码
     */
    private boolean usingMediaCodec = false;
    /**
     * 使用编解码是否自转
     */
    private boolean usingMediaCodecAutoRotate = false;
    private boolean usingOpenSLES = false;
    /**
     * Auto Select=,RGB 565=fcc-rv16,RGB 888X=fcc-rv32,YV12=fcc-yv12,默认为RGB 888X
     */
    private String pixelFormat = "";//Auto Select=,RGB 565=fcc-rv16,RGB 888X=fcc-rv32,YV12
    private boolean enableBackgroundPlay = false;
    /**
     * 媒体播放器
     */
    public IMediaPlayer mMediaPlayer;
    private Context mAppContext;

    public static MediaManager instance(Context context) {
        if (JCMediaManager == null) {
            JCMediaManager = new MediaManager(context);
        }
        return JCMediaManager;
    }

    private MediaManager(Context context) {
        mAppContext = context;
        mMediaHandlerThread = new HandlerThread(TAG);
        mMediaHandlerThread.start();
        mMediaHandler = new MediaHandler((mMediaHandlerThread.getLooper()));
        mainThreadHandler = new Handler();
    }

    public Point getVideoSize() {
        if (currentVideoWidth != 0 && currentVideoHeight != 0) {
            return new Point(currentVideoWidth, currentVideoHeight);
        } else {
            return null;
        }
    }


    public class MediaHandler extends Handler {

        public MediaHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case HANDLER_PREPARE:
                    initPlayer();
                    //try {
                    //    currentVideoWidth = 0;
                    //    currentVideoHeight = 0;
                    //    mediaPlayer.release();
                    //    mediaPlayer = new MediaPlayer();
                    //    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    //    mediaPlayer.setLooping(CURRENT_PLING_LOOP);
                    //    mediaPlayer.setOnPreparedListener(JCMediaManager.this);
                    //    mediaPlayer.setOnCompletionListener(JCMediaManager.this);
                    //    mediaPlayer.setOnBufferingUpdateListener(JCMediaManager.this);
                    //    mediaPlayer.setScreenOnWhilePlaying(true);
                    //    mediaPlayer.setOnSeekCompleteListener(JCMediaManager.this);
                    //    mediaPlayer.setOnErrorListener(JCMediaManager.this);
                    //    mediaPlayer.setOnInfoListener(JCMediaManager.this);
                    //    mediaPlayer.setOnVideoSizeChangedListener(JCMediaManager.this);
                    //    Class<MediaPlayer> clazz = MediaPlayer.class;
                    //    Method method = clazz.getDeclaredMethod("setDataSource", String.class, Map.class);
                    //    method.invoke(mediaPlayer, CURRENT_PLAYING_URL, MAP_HEADER_DATA);
                    //    mediaPlayer.prepareAsync();
                    //    mediaPlayer.setSurface(new Surface(savedSurfaceTexture));
                    //} catch (Exception e) {
                    //    e.printStackTrace();
                    //}
                    break;
                case HANDLER_RELEASE:
                    if (mMediaPlayer != null) {
                        mMediaPlayer.release();
                    }
                    break;
            }
        }
    }

    public void prepare() {
        releaseMediaPlayer();
        Message msg = new Message();
        msg.what = HANDLER_PREPARE;
        mMediaHandler.sendMessage(msg);
    }

    public void releaseMediaPlayer() {
        Message msg = new Message();
        msg.what = HANDLER_RELEASE;
        mMediaHandler.sendMessage(msg);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
        Log.i(TAG,
                "onSurfaceTextureAvailable [" + VideoPlayerManager.getCurrentJcvd().hashCode() +
                        "] ");
        if (savedSurfaceTexture == null) {
            savedSurfaceTexture = surfaceTexture;
            prepare();
        } else {
            textureView.setSurfaceTexture(savedSurfaceTexture);
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
        // 如果SurfaceTexture还没有更新Image，则记录SizeChanged事件，否则忽略
        Log.i(TAG,
                "onSurfaceTextureSizeChanged [" + VideoPlayerManager.getCurrentJcvd().hashCode() +
                        "] ");
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        return savedSurfaceTexture == null;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
    }

    @Override
    public void onPrepared(IMediaPlayer mp) {
        mMediaPlayer.start();
    }

    @Override
    public void onCompletion(IMediaPlayer mp) {
        mainThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                if (VideoPlayerManager.getCurrentJcvd() != null) {
                    VideoPlayerManager.getCurrentJcvd().onAutoCompletion();
                }
            }
        });
    }

    @Override
    public void onBufferingUpdate(IMediaPlayer mp, final int percent) {
        mainThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                if (VideoPlayerManager.getCurrentJcvd() != null) {
                    VideoPlayerManager.getCurrentJcvd().setBufferProgress(percent);
                }
            }
        });
    }

    @Override
    public void onSeekComplete(IMediaPlayer mp) {
        mainThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                if (VideoPlayerManager.getCurrentJcvd() != null) {
                    VideoPlayerManager.getCurrentJcvd().onSeekComplete();
                }
            }
        });
    }

    @Override
    public boolean onError(IMediaPlayer mp, final int what, final int extra) {
        mainThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                if (VideoPlayerManager.getCurrentJcvd() != null) {
                    VideoPlayerManager.getCurrentJcvd().onError(what, extra);
                }
            }
        });
        return true;
    }

    @Override
    public boolean onInfo(IMediaPlayer mp, final int what, final int extra) {
        mainThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                if (VideoPlayerManager.getCurrentJcvd() != null) {
                    VideoPlayerManager.getCurrentJcvd().onInfo(what, extra);
                }
            }
        });
        return false;
    }

    @Override
    public void onVideoSizeChanged(IMediaPlayer mp, int var1, int var2, int var3, int var4) {
        currentVideoWidth = 1080;
        currentVideoHeight = 1920;
        LogUtil.e("ccx onVideoSizeChanged currentVideoWidth==="+currentVideoWidth);
        LogUtil.e("ccx onVideoSizeChanged currentVideoHeight==="+currentVideoHeight);
        mainThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                if (VideoPlayerManager.getCurrentJcvd() != null) {
                    VideoPlayerManager.getCurrentJcvd().onVideoSizeChanged();
                }
            }
        });
    }

    private void initPlayer() {
        try {
            if (usingAndroidPlayer) {
                mMediaPlayer = new AndroidMediaPlayer();
            } else {
                IjkMediaPlayer ijkMediaPlayer = null;
                if (CURRENT_PLAYING_URL != null) {
                    ijkMediaPlayer = new IjkMediaPlayer();
                    ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);

                    if (usingMediaCodec) {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
                        if (usingMediaCodecAutoRotate) {
                            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
                        } else {
                            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
                        }
                    } else {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
                    }

                    if (usingOpenSLES) {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 1);
                    } else {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
                    }

                    if (TextUtils.isEmpty(pixelFormat)) {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
                    } else {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", pixelFormat);
                    }
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
                    ijkMediaPlayer.setScreenOnWhilePlaying(true);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 10000000);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", 1);

                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
                }
                mMediaPlayer = ijkMediaPlayer;
            }

            if (enableBackgroundPlay) {
                mMediaPlayer = new TextureMediaPlayer(mMediaPlayer);
            }

            // TODO: create SubtitleController in MediaPlayer, but we need
            // a context for the subtitle renderers
            // REMOVED: SubtitleController

            // REMOVED: mAudioSession
            /**视频准备播放监听*/
            mMediaPlayer.setOnPreparedListener(this);
            /**视频播放完成监听*/
            mMediaPlayer.setOnCompletionListener(this);
            /**视频错误监听*/
            mMediaPlayer.setOnErrorListener(this);
            /**视频其他信息监听*/
            mMediaPlayer.setOnInfoListener(this);
            /**视频界面大小改变监听*/
            mMediaPlayer.setOnVideoSizeChangedListener(this);
            /**视频缓冲监听*/
            mMediaPlayer.setOnBufferingUpdateListener(this);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && usingAndroidPlayer &&
                    (TextUtils.isEmpty(CURRENT_PLAYING_URL) ||
                            CURRENT_PLAYING_URL.equalsIgnoreCase("file"))) {
                IMediaDataSource dataSource =
                        new FileMediaDataSource(new File(CURRENT_PLAYING_URL.toString()));
                mMediaPlayer.setDataSource(dataSource);
            } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

                mMediaPlayer.setDataSource(mAppContext, Uri.parse(CURRENT_PLAYING_URL), MAP_HEADER_DATA);
            } else {
                mMediaPlayer.setDataSource(CURRENT_PLAYING_URL.toString());
            }
            LogUtil.e("ccx ==="+CURRENT_PLAYING_URL);
            mMediaPlayer.setSurface(new Surface(savedSurfaceTexture));
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mMediaPlayer.prepareAsync();

            // REMOVED: mPendingSubtitleTracks

            // we don't set the target state here either, but preserve the target state that was there before.我们这里不设置目标状态,但保护的目标状态
            //mCurrentState = PlayStateParams.STATE_PREPARING;
            //attachMediaController();
        } catch (IOException ex) {
            ex.printStackTrace();
            //Log.w(TAG, "Unable to open content: " + mUri, ex);
            //mCurrentState = PlayStateParams.STATE_ERROR;
            //mTargetState = PlayStateParams.STATE_ERROR;
            //mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
            //Log.w(TAG, "Unable to open content: " + mUri, ex);
            //mCurrentState = PlayStateParams.STATE_ERROR;
            //mTargetState = PlayStateParams.STATE_ERROR;
            //mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // REMOVED: mPendingSubtitleTracks.clear();
        }
    }
}
